#include <stdio.h>
#include <stdlib.h>
#include <string.h>				
#include "oLED.h"
#include "queue.h"
#include "Serial.h"
//#include "SDCard.h"
#include "efile.h"

#define X86 0
#define BUFFERSIZE 10
#define TRUE 1
#define FALSE 0

char CLEAR[6] = {0x1B, 0x5B, 0x32, 0x4B, 0x0D, 0x00};

extern queue RX;
extern queue TX;

int DEVICE = 0;
int LINE0 = 0;
int LINE1 = 0;
/* For SD control */
char SD_MODE;


///******** Interp_SD ****************************************************************/
///************************************************************************************/
//int Interp_SD(char * brk) {
//    char args[20];
//	char * arguement = &args[0];
//	char * next, * token, * token2;
//	char data[1];
//
//	arguement = strtok_r(NULL, "-", &brk);
//	while(arguement != NULL) {
//		switch (arguement[0]) {
//		    // Format
//			case 'F':
//			case 'f':
//				token = strtok_r(arguement, " ", &next);
//#if X86
//				if (strcmp(token, "format") != 0) 
//					return 1;
//#endif		
//				if (eFile_Format()) return 1;
//				break;
//
//		    // Directory (ls)
//			case 'L':
//			case 'l':
//				token = strtok_r(arguement, " ", &next);
//#if X86
//				if (strcmp(token, "ls") != 0) 
//					return 1;
//#endif		
//				if (eFile_Directory()) return 1;
//				break;
//
//		    // Create (new)
//			case 'N':
//			case 'n':
//				token = strtok_r(arguement, " ", &next);
//#if X86
//				if (strcmp(token, "new") != 0) 
//					return 1;
//#endif		
//				token = strtok_r(NULL, " ", &next);
//				if (eFile_Create(token)) return 1;
//				break;
//
//		    // Open file
//			case 'O':
//			case 'o':
//				token = strtok_r(arguement, " ", &next);
//#if X86
//				if (strcmp(token, "open") != 0) 
//					return 1;
//#endif		
//				token = strtok_r(NULL, " ", &next);
//				token2 = strtok_r(NULL, " ", &next);
//				if (*token == 'w') {
//				  // Wopen
//				  if (eFile_WOpen(token2)) return 1;
//				} else if (*token == 'r') { 
//				  // Ropen
//				  if (eFile_ROpen(token2)) return 1;
//				} else return 1;
//				break;
//
//		    // Close file
//			case 'C':
//			case 'c':
//				token = strtok_r(arguement, " ", &next);
//#if X86
//				if (strcmp(token, "close") != 0) 
//					return 1;
//#endif		
//				token = strtok_r(NULL, " ", &next);
//				if (*token == 'w') {
//				  // Wclose
//				  if (eFile_WClose()) return 1;
//				} else if (*token == 'r') { 
//				  // Rclose
//				  if (eFile_RClose()) return 1;
//				} else {
//				  if (eFile_Close()) return 1;
//				}
//				break;
//
//		    // write
//			case 'W':
//			case 'w':
//				token = strtok_r(arguement, " ", &next);
//#if X86
//				if (strcmp(token, "write") != 0) 
//					return 1;
//#endif		
//				token = strtok_r(NULL, " ", &next);
//				token2 = strtok_r(NULL, " ", &next);
//				if (eFile_Write(*token2)) return 1;
//				break;
//				
//		    // read
//			case 'R':
//			case 'r':
//				token = strtok_r(arguement, " ", &next);
//#if X86
//				if (strcmp(token, "read") != 0) 
//					return 1;
//#endif		
//				token = strtok_r(NULL, " ", &next);
//				if (eFile_ReadNext(data)) return 1;
//				Uart_SendString(data);
//				break;
//				
//		    // Delete
//			case 'D':
//			case 'd':
//				token = strtok_r(arguement, " ", &next);
//#if X86
//				if (strcmp(token, "delete") != 0) 
//					return 1;
//#endif		
//				token = strtok_r(NULL, " ", &next);
//				if (eFile_Delete(token)) return 1;
//				break;				
//
//		    // display help to console
//			case 'H':
//			case 'h':
//#if X86
//				token = strtok_r(arguement, " ", &next);
//				if (strcmp(token, "help") != 0) 
//					return 1;
//#endif
//				Uart_SendString("\r\n");
//				Uart_SendString("-format: format disk\r\n");
//				Uart_SendString("-create: create file\r\n");
//				Uart_SendString("-help  : print commands\r\n");
//				Uart_SendString("\r\n");
//				break;
//
//			default:
//				return 1;
//		}
//		arguement = strtok_r(NULL, "-", &brk);
//	}
//	return 0;
//}
//
///************************************************************************************/

int Interp_Display(char * brk) {
	char * arguement;
	char * token;
	char * next;
	char message[21];
	int arg;
	int k = 0;
	int l = 0;
	
	arguement = strtok_r(NULL, "-", &brk);
	while(arguement != NULL) {
		switch (arguement[0]) {
			// set device
			case 'S':
			case 's':
				token = strtok_r(arguement, " ", &next);
#if X86
				if (strcmp(token, "set") != 0) 
					return 1;
#endif
					
				token = strtok_r(NULL, " ", &next);
				arg = atoi(token);
				arg--;
				if (arg > 1 || arg < 0)
					return 1;

				DEVICE = arg;
				break;
				
			// set contrast
			case 'C':
			case 'c':
				token = strtok_r(arguement, " ", &next);
#if X86
				if (strcmp(token, "con") != 0) 
					return 1;
#endif
				
				token = strtok_r(NULL, " ", &next);
				arg = atoi(token);
				arg--;
				if (arg > 15 || arg < 0)
					return 1;
				
				oLED_Contrast(arg);
				break;
				
			// set line
			case 'L':
			case 'l':
				token = strtok_r(arguement, " ", &next);
#if X86
				if (strcmp(token, "line") != 0) 
					return 1;
#endif
				
				token = strtok_r(NULL, " ", &next);
				arg = atoi(token);
				arg--;
				if (arg > 4 || arg < 0)
					return 1;
				
				if (DEVICE == 0)
					LINE0 = arg;
				else
					LINE1 = arg;
				break;
				
		    // display help to console
			case 'H':
			case 'h':
#if X86
				token = strtok_r(arguement, " ", &next);
				if (strcmp(token, "help") != 0) 
					return 1;
#endif
				Uart_SendString("\r\n");
				Uart_SendString("-set [1-2]\r\n");
				Uart_SendString("-con [1-16]\r\n");
				Uart_SendString("-help\r\n");
				Uart_SendString("-line [1-5]\r\n");
				Uart_SendString("-\"*+\"\r\n");
				Uart_SendString("\r\n");
				break;

				
			// print message
			case '"':
				// determine message
				while(arguement[k] != '"'){
#if X86
					if(arguement[k] == 0x00)
						return 1;
#endif
					k++;
				}
				k++;
				while(arguement[k] != '"'){
					if(arguement[k] == '\\'){
						k++;
					}
					message[l] = arguement[k];
					k++; l++; 
				}
				message[l] = 0x00;
				
				if(DEVICE == 0) {
					oLED_String(DEVICE, LINE0, message);
					LINE0++;
					if (LINE0 == 5)
						LINE0 = 0;

				} else {
					oLED_String(DEVICE, LINE1, message);
					LINE1++;
					if (LINE1 == 5)
						LINE1 = 0;
				}
				break;

			default:
				return 1;
		}
		
		arguement = strtok_r(NULL, "-", &brk);
	}
	return 0;
}

int Interpreter (void) {
	// initialize
	char * commands[6];
	static char string [BUFFERSIZE][50];
	char temp[50];
	char * brk;
	char * token;
	char next_char;
	int line = 0;
	int last = 0;
	int current = 0;
	int next = 0;
	
	// possible commands
	commands[0] = "quit";
	commands[1] = "sleep";
	commands[2] = "block";
	commands[3] = "display";
	commands[4] = "sd";
	commands[5] = "adc";
	
	//main loop
	while (1) {
		int i = 0;
		int z = 0;								
		int out;
		Uart_SendString("(");
		Uart_SendInt(line);
		Uart_SendString(")>");

		//read fifo into string
		while(1) {
			if(queue_empty(&RX) == TRUE) {}	
			else {
				next_char = queue_remove(&RX);
				if(next_char == 0x1B) {
				  while(queue_empty(&RX) == TRUE) {}
				  next_char = queue_remove(&RX);
				  if(next_char == 0x5B) {
				    while(queue_empty(&RX) == TRUE) {}
				    next_char = queue_remove(&RX);
					if(next_char == 0x41) {
				      if(current == last) {}
					  else {
					    int a = 0;
						if(current == 0)
						  current = BUFFERSIZE - 1;
						else
						  current = current - 1;
						while(string[current][a] != '\0') {
						  string[next][a] = string[current][a];
						  a++;
						}
						i = a;
					  }   
					}
					if(next_char == 0x42) {
					  if(current == next) {}
					  else {
				        int a = 0;
						current = (current + 1) % BUFFERSIZE;
						if(current == next) {
						  string[next][0] = '\0';
						  i = 0;
						} else {
						  while(string[current][a] != '\0') {
						    string[next][a] = string[current][a];
						    a++;
						  }
						  i = a;
					    }
					  }
					}
					Uart_SendString(CLEAR);
				    Uart_SendString("(");
					Uart_SendInt(line);
					Uart_SendString(")>");
					Uart_SendString(string[current]);
				  }
				}
                else if((next_char == 8)||(next_char == 127)) {
					
					i = i-1;
				}
                else if(next_char == 13) {
					string[next][i] = '\0';
					out = next;
				    next = (next + 1) % BUFFERSIZE;
					if(next == last)
					  last = (last + 1)	% BUFFERSIZE;
				    string[next][0] = '\0';
					current = next;
					break;
				}
				else {
				    string[next][i] = next_char;
					i++;
				}
			}
		}

		//copy current string to temp
		while(string[out][z] != '\0') {
			temp[z] = string[out][z];
			z++;
		}
		temp[z] = '\0';
		
		//determine first token
		token = strtok_r(temp, " ", &brk);
		
		//kill
		if (strcmp(token, commands[0]) == 0) { 
			//OS_Kill();
			break;
		}
		//sleep
		else if (strcmp(token, commands[1]) == 0) {
			//OS_Sleep();
			break;
		}
		//block
		else if (strcmp(token, commands[2]) == 0) {
			
		}
		//display
		else if (strcmp(token, commands[3]) == 0) {
			if(Interp_Display(brk))
				Uart_SendString("Display failed. Try display -help for use.\r\n");
		}
		//sd
//		else if (strcmp(token, commands[4]) == 0) {
////		  SD_MODE = 1;
////		  SD_Cmd();
//		  if (eFile_Init())
//		    Uart_SendString("SD failed. Try display -help for use.\r\n");
//		  if(Interp_SD(brk))
//		    Uart_SendString("SD failed. Try display -help for use.\r\n");	
//		}
		//adc
		else if (strcmp(token, commands[5]) == 0) {
			
		}

		line++;
	}
	
	return 0;
}

unsigned char namePrompt[] = "\n\rPlease Enter a File Name: ";
int GetFileName(char *file){
  int i;
  unsigned char charGet;

  UARTSend(namePrompt, 27);

  CommandComplete = 0;
  while(!CommandComplete){}
  
  i= 0;
  while(RxFifo_Get(&charGet) && charGet != 0x0D && i<9){
     *file++ = charGet;
	 i++;
  }

  if(i<10){
	*file = 0x00;
	return i;
  }
  else
    return 0;
}
